#include <iostream>
#include <memory>
#include <string>
#include <queue>
#include <mutex>
#include "include/TcpSocket.hpp"
#include "ConnectionFactory.hpp"
#include "Reactor.hpp"
#include "SubReactors.hpp"
#include "EventHandler.hpp"

void usage(std::string proc_name)
{
    std::cout << "usage: \n\t" << proc_name << " port\n" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        usage(argv[0]);
        return 1;
    }
    uint16_t port = std::stoi(argv[1]);

    std::mutex mtx;
    std::queue<int> eventQueue;
    int efd = eventfd(0, EFD_NONBLOCK);
    if(efd == -1)
    {
        log.message(INFO, "eventfd error...");
        return 1;
    }

    std::unique_ptr<Reactor> mainReactor = std::make_unique<Reactor>(efd, &mtx, &eventQueue);
    std::unique_ptr<SubReactors> subReactors = std::make_unique<SubReactors>(efd, &mtx, &eventQueue);

    std::unique_ptr<Socket> listen_sock = std::make_unique<TcpSocket>();
    listen_sock->createListenSocket(port);
    setNonBlock(listen_sock->getSocketFd());

    std::unique_ptr<EventHandler> eventHandler = std::make_unique<EventHandler>();
    auto reader = std::bind(&EventHandler::acceptForSubReactor, std::placeholders::_1);

    mainReactor->addConnection(ConnectionFactory::createListenConnection(
        listen_sock->getSocketFd(), reader, EPOLLIN|EPOLLET, mainReactor.get()));
    mainReactor->start();
    
    return 0;
}